This vignette assumes a SQL server at localhost (we
use PostgreSQL), with data in OMOP Common Data Model v5.4 format in
schema cdm_new_york3. The patient records shown in this
example are synthetic data from Synthea(TM) Patient
Generator.
library(phea)
library(dplyr)
# Connect to SQL server.
dbcon <- DBI::dbConnect(RPostgres::Postgres(),
host = 'localhost', port = 7654, dbname = 'fort',
user = cred$pg$user, password = cred$pg$pass)
# Call setup_phea so we can use sqlt() and sql0().
setup_phea(dbcon, 'cdm_new_york3')
In this vignette we identify:
Case A.
Case B.
Here’s how we compute it:
In both cases, we will normalize the unit of measurement of SCr to md/dL prior to computing formulas. We could also use formulas to convert the units, and the result would be the same.
We collect SCr records from MEASUREMENT and convert the
units to mg/dL.
# 3051825 38483-4 Creatinine [Mass/volume] in Blood
# 3016723 2160-0 Creatinine [Mass/volume] in Serum or Plasma
# "A" records: Unit is 'mg/dL'
scr_records_a <- sqlt(measurement) |>
filter(measurement_concept_id %in% c(3051825, 3016723) &&
unit_source_value == 'mg/dL')
# "B" records: Unit is 'µmol/L', but we convert to 'mg/dL'
scr_records_b <- sqlt(measurement) |>
filter(measurement_concept_id %in% c(3051825, 3016723) &&
unit_source_value == 'µmol/L') |>
mutate( # Convert µmol/L to mg/dL
value_as_number = value_as_number / 88.42,
unit_source_value = 'mg/dL')
# Combine all available serum creatinine records into a single record source.
scr_record_source <- union_all(scr_records_a, scr_records_b) |>
make_record_source(
ts = measurement_datetime,
pid = person_id)
We collect GFR records from MEASUREMENT.
## GFR
# 46236952 77147-7 Glomerular filtration rate/1.73 sq M.predicted [Volume Rate/Area] in Serum, Plasma or Blood by Creatinine-based formula (MDRD)
gfr_record_source <- sqlt(measurement) |>
filter(measurement_concept_id == 46236952) |>
make_record_source(
ts = measurement_datetime,
pid = person_id)
Formula scr_03_criteria contains the logic of case A
(difference >= 0.3 mg/dL), while scr_15_criteria
contains case B (ratio >= 1.5).
scr_change <- calculate_formula(
components = list(
# Current SCr
scr = make_component(scr_record_source),
# Minimum value within 48-hour window
scr_48h_min = make_component(scr_record_source,
window = '48 days', .delay_fn = 'min'),
# Minimum value within 7-day window
scr_7d_min = make_component(scr_record_source,
window = '7 months', .delay_fn = 'min'),
# Current glomerular filtration rate (GFR)
gfr = make_component(gfr_record_source),
# Glomerular filtration rate 3 to 5 months older than phenotype date
gfr_3mo = make_component(gfr_record_source,
delay = '3 months', window = '5 months')),
fml = list(
scr_03_criteria = 'scr_value_as_number - scr_48h_min_value_as_number >= 0.3',
scr_15_criteria = 'scr_value_as_number / scr_7d_min_value_as_number >= 1.5',
gfr_criteria = 'gfr_value_as_number < 60 AND gfr_3mo_value_as_number < 60'),
export = c(
'scr_measurement_datetime',
'scr_48h_min_measurement_datetime',
'scr_7d_min_measurement_datetime',
'gfr_measurement_datetime',
'gfr_3mo_measurement_datetime')
)
scr_change |>
select(-ends_with('datetime')) |>
phea_plot(22444)
#> Collecting lazy table, done.
To see the SQL query underlying the phenotype, use helper function
code_shot(), or dbplyr::sql_render(), or the
.clip_sql option in calculate_formula().